import { reactive, computed, toRefs, ref } from 'vue'
import type { PageableModel, StatePropsModel } from '@/components/kitegoTable/type.ts'

/**
 * @description table 页面操作方法封装
 * @param {Function} api 获取表格数据 api 方法 (必传)
 * @param {Object} initParam 获取数据初始化参数 (非必传，默认为{})
 * @param {Boolean} isPageable 是否有分页 (非必传，默认为true)
 * @param {Function} dataCallBack 对后台返回的数据进行处理的方法 (非必传)
 */
export const useTable = (
    api: any = {},
    initParam: object = {},
    isPageable: boolean = true,
    dataCallBack?: (data: any) => any
) => {
    const state = reactive<StatePropsModel>({
        tableData: [], // 表格数据
        pageable: {
            page: 1, // 当前页数
            pageSize: 20, // 每页显示条数
            total: 0 // 总条数
        },
        searchParam: {}, // 查询参数(只包括查询)
        totalParam: {}, // 总参数(包含分页和查询参数)
        loading: false // 是否加载完毕
    })

    /**
     * @description 分页查询参数(只包括分页和表格字段排序,其他排序方式可自行配置)
     */
    const pageParam = computed({
        get: () => {
            return {
                page: state.pageable.page,
                pageSize: state.pageable.pageSize
            }
        },
        set: (_newVal: any) => {
            console.log(_newVal, '_newVal')
        }
    })

    /**
     * @description 获取表格数据
     */
    const getTableList = async () => {
        if (!api) return
        state.loading = true

        // 先把初始化参数和分页参数放到总参数里面
        Object.assign(state.totalParam, initParam, isPageable ? pageParam.value : {})
        let data = await api.get({ ...state.totalParam })

        // 返回数据处理
        if (dataCallBack) data = dataCallBack(data)
        state.tableData = isPageable ? data.data : data

        // 解构后台返回的分页数据 (如果有分页更新分页信息)
        if (isPageable) {
            const page = data.currentPage
            const pageSize = data.perPage
            const total = data.total
            updatePageable({ page, pageSize, total })
        }

        state.loading = false
    }

    /**
     * @description 更新查询参数
     */
    const updatedTotalParam = () => {
        state.totalParam = {}
        // 处理查询参数，可以给查询参数加自定义前缀操作
        const nowSearchParam: StatePropsModel['searchParam'] = {}
        // 防止手动清空输入框携带参数（这里可以自定义查询参数前缀）
        for (const key in state.searchParam) {
            // 某些情况下参数为 false/0 也应该携带参数
            if (
                state.searchParam[key] ||
                state.searchParam[key] === false ||
                state.searchParam[key] === 0
            ) {
                nowSearchParam[key] = state.searchParam[key]
            }
        }
        Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {})
    }

    /**
     * @description 更新分页信息
     * @param {Object} pageable 后台返回的分页数据
     */
    const updatePageable = (pageable: PageableModel) => {
        Object.assign(state.pageable, pageable)
    }

    /**
     * @description 表格数据查询
     */
    const search = () => {
        state.pageable.page = 1
        updatedTotalParam()
        getTableList()
    }

    /**
     * @description 表格数据重置
     */
    const reset = () => {
        state.pageable.page = 1
        state.searchParam = {}
        updatedTotalParam()
        getTableList()
    }

    /**
     * @description 每页条数改变
     * @param {Number} val 当前条数
     */
    const handleSizeChange = (val: number) => {
        state.pageable.page = 1
        state.pageable.pageSize = val
        getTableList()
    }

    /**
     * @description 当前页改变
     * @param {Number} val 当前页
     */
    const handleCurrentChange = (val: number) => {
        state.pageable.page = val
        getTableList()
    }

    return {
        ...toRefs(state),
        getTableList,
        search,
        reset,
        handleSizeChange,
        handleCurrentChange,
        updatedTotalParam
    }
}

/**
 * @description 表格多选数据操作
 * @param {String} rowKey 当表格可以多选时，所指定的 id
 */
export const useSelection = (rowKey: string = 'id') => {
    const isSelected = ref<boolean>(false)
    const selectedList = ref<{ [key: string]: any }[]>([])

    // 当前选中的所有 keys 数组
    const selectedListKeys = computed((): string[] => {
        const keys: string[] = []
        selectedList.value.forEach((item) => keys.push(item[rowKey]))

        return keys
    })

    /**
     * @description 多选操作
     * @param {Array} rowArr 当前选择的所有数据
     * @return void
     */
    const selectionChange = (rowArr: { [key: string]: any }[]) => {
        isSelected.value = !!rowArr.length
        selectedList.value = rowArr
    }

    return {
        isSelected,
        selectedList,
        selectedListKeys,
        selectionChange
    }
}
